package adventure;

import adventure.commands.*;
import adventure.commands.admin.*;
import adventure.room.RoomManager;
import player.Player;

/**
 *
 * @author Michael Hanns
 *
 */
public class AdventureInputImp implements AdventureInput {

    private Adventure adv;
    private RoomManager rooms;
    private AbstractCommand[] commands;

    public AdventureInputImp(Adventure a) {
        adv = a;
        rooms = ((AdventureEdit) adv).getRoomManager();
        instantiateCommands();
    }

    private void instantiateCommands() {
        commands = new AbstractCommand[45];

        // Movement
        commands[0] = new CompassMovement(adv);
        commands[1] = new GoMove(adv);
        commands[2] = new Run(adv);
        commands[3] = new Recall(adv);

        // Doors
        commands[4] = new Open(adv);
        commands[5] = new Close(adv);
        commands[6] = new Unlock(adv);

        // Look
        commands[7] = new Look(adv);

        // Items
        commands[8] = new Get(adv);
        commands[9] = new Drop(adv);
        commands[10] = new Give(adv);
        commands[11] = new Inventory(adv);
        commands[12] = new Consume(adv);
        commands[13] = new Equip(adv);
        commands[14] = new Remove(adv);
        commands[15] = new Compare(adv);

        // Combat
        commands[16] = new Status(adv);
        commands[17] = new Consider(adv);
        commands[18] = new Kill(adv);
        commands[19] = new Flee(adv);
        commands[20] = new Loot(adv);

        // Communication
        commands[21] = new Say(adv);
        commands[22] = new Tell(adv);
        commands[23] = new Emote(adv);
        commands[24] = new Subscriptions(adv);

        // User Options/Tools
        commands[25] = new SetDescription(adv);
        commands[26] = new SetPassword(adv);
        commands[27] = new SetSuppressTick(adv);
        commands[28] = new RecordSpeedwalk(adv);
        commands[29] = new SearchHelp(adv);

        // Log
        commands[30] = new Log(adv);

        // Map
        commands[31] = new Map(adv);

        // Party
        commands[32] = new Follow(adv);
        commands[33] = new Group(adv);
        
        // Trade
        commands[34] = new Purchase(adv);
        commands[35] = new Sell(adv);
        
        // Skills
        commands[36] = new Skills(adv);
        
        // Admin
        commands[37] = new SpawnItem(adv);
        commands[38] = new SpawnMobile(adv);
        commands[39] = new SpawnTrigger(adv);
        commands[40] = new AdminPromote(adv);
        commands[41] = new AdminDemote(adv);
        commands[42] = new ChangeName(adv);
        commands[43] = new MovePlayer(adv);
        commands[44] = new Immortal(adv);
    }

    @Override
    public void leaveGame(Player activePlayer) {
        adv.playerQuit(activePlayer);
    }

    @Override
    public Adventure getAdventure() {
        return adv;
    }

    @Override
    public synchronized String processCommand(Player player, String input) {
        if (input.length() == 0) {
            return player.getStatusPrompt();
        }
        System.out.println("Processing " + player.getAliveName() + "'s command.");
        
        if (!player.isDead()) {
            String[] commandArgs = input.split(" ");

            if (commandArgs.length == 0) {
                return player.getStatusPrompt();
            } else {
                // Enter room, just in case
                if (rooms.getRoomPlayer(player.x(), player.y(),
                        player.z(), player.getName()) == 0) {
                    rooms.enterRoom(player);
                }

                String output = "";
                // Try the triggers foremost (triggers override commands)
                output = adv.tripTriggers(player, input);

                if (output.length() > 0) {
                    return output + "\n\n" + player.getStatusPrompt();
                }
                
                // Try a standard command
                System.out.println("Trying a standard command");
                for (int c = 0; c < commands.length; c++) {
                    if (commands[c].isCommand(commandArgs[0])) {
                        output = commands[c].validateAndExecute(player, commandArgs);
                        // Circumstantial triggers are only tripped when you enter a room
                        //String triggerOut = adv.tripTriggers(player);
                        //if (triggerOut.length() > 0) {
                        //    output += "\n" + triggerOut;
                        //}
                        
                        return output + "\n\n" + player.getStatusPrompt();
                    }
                }

                // Try a player skill
                System.out.println("Trying to perform a skill.");
                output = player.performSkill(commandArgs);

                if (output.length() > 0) {
                    //String triggerOut = adv.tripTriggers(player);
                    //if (triggerOut.length() > 0) {
                    //    output += "\n" + triggerOut;
                    //}
                    return output + "\n\n" + player.getStatusPrompt();
                }
                
                // If all else fails, try the triggers alone
                //output = adv.tripTriggers(player);
                
                // In reality, don't trip triggers if it's not a real command
                // Durr

                //if (output.length() > 0) {
                //    return output + "\n\n" + player.getStatusPrompt();
                //} else {
                    return "Command not recognised.\n";
                //}
            }
        } else {
            if (input.equalsIgnoreCase("RESPAWN")) {
                return adv.respawnPlayer(player);
            } else {
                return "You are dead! Type RESPAWN to respawn to your closest checkpoint.";
            }
        }
    }
}
